<?php
namespace sef;

class core {

	static public function start() {
		// 注册autoload方法
		spl_autoload_register('self::autoload');

		// 设定错误和异常处理
		//register_shutdown_function('sef\core::fatal_error');
		//set_error_handler('sef\core::app_error');
		//set_exception_handler('sef\core::app_exception');

		include_once CORE_PATH . 'config.php';

		include_once CORE_PATH . 'log.php';
		include_once CORE_PATH . 'filter.php';
		include_once CORE_PATH . 'cache.php';

		include_once CORE_PATH . 'db.php';
		include_once CORE_PATH . 'model.php';
		include_once CORE_PATH . 'auth.php';
		include_once CORE_PATH . 'view.php';
		include_once CORE_PATH . 'controller.php';
		include_once CORE_PATH . 'function.php';

		include_once FRAMEWORK_PATH . 'conf/config.php';
		include_once FRAMEWORK_PATH . 'ext/function.php';

		session_start();

		$app_name = strtolower(get('app'));
		if (empty($app_name)) {
			$app_name = 'index';
		}
		if (!filter::app_name($app_name)) {
			trigger_error('应用名称不合法', E_USER_ERROR);
		}

		$method_name = strtolower(get('method'));
		if (empty($method_name)) {
			$method_name = 'index';
		}

		if (!filter::app_name($method_name)) {
			trigger_error('方法名称不合法', E_USER_ERROR);
		}

		define('APP_NAME', $app_name);
		define('METHOD_NAME', $method_name);

		$app_controller_class = $app_name . '_controller';
		$app_controller_file = APP_PATH . $app_name . DS . $app_controller_class . '.php';

		if (is_file($app_controller_file)) {
			//加载controller文件
			require ($app_controller_file);			
			$app = new $app_controller_class;

			$method = new \ReflectionMethod($app, $method_name);
			if ($method -> isPublic() && !$method -> isStatic()) {
				// URL参数绑定检测
				if ($method -> getNumberOfParameters() > 0) {
					$vars = $_REQUEST;
					$params = $method -> getParameters();
					$args = array();
					foreach ($params as $param) {
						$name = $param -> getName();
						if (isset($vars[$name])) {
							$args[] = $vars[$name];
						} elseif ($param -> isDefaultValueAvailable()) {
							$args[] = $param -> getDefaultValue();
						} else {
							trigger_error('缺少' . $name . '参数', E_USER_ERROR);
						}
					}$method -> invokeArgs($app, $args);
				} else {
					$method -> invoke($app);
				}
			}
		} else {
			trigger_error('未找到控制器文件' . $app_controller_file, E_USER_ERROR);
		}
	}

	public static function autoload($class_name) {

		if (strpos($class_name, '_model') !== false) {
			$model_name = str_replace('_model', '', $class_name);
			$model_path = APP_PATH . $model_name . DS . $class_name . '.php';
			include_once $model_path;
		}

		if (strpos($class_name, '_controller') !== false) {
			$controller_name = str_replace('_controller', '', $class_name);
			$controller_path = APP_PATH . $controller_name . DS . $class_name . '.php';
			include_once $controller_path;
		}
	}

	/**
	 * 自定义异常处理
	 * @access public
	 * @param mixed $e 异常对象
	 */

	static public function app_exception($e) {

		$error = array();
		$error['message'] = $e -> getMessage();
		$trace = $e -> getTrace();
		//print_r($trace);
		$error['file'] = $e -> getFile();
		$error['line'] = $e -> getLine();
		$error['trace'] = $e -> getTraceAsString();

		//log::add($error['message']);
		// 发送404信息
		//header('HTTP/1.1 404 Not Found');
		//header('Status:404 Not Found');

		self::halt($error);
	}

	/**
	 * 自定义错误处理
	 * @access public
	 * @param int $errno 错误类型
	 * @param string $errstr 错误信息
	 * @param string $errfile 错误文件
	 * @param int $errline 错误行数
	 * @return void
	 */
	static public function app_error($err_no, $error_str, $err_file, $err_line) {
		//self::halt();
		//print_r($err_no);
		//print_r(error_get_last());
		debug_print_backtrace();
		//print_r($err_no);
		//print_r($err_file);
		//print_r($err_line);

		//$error['err_no'] = $err_no;
		//$error['error_str'] = $error_str;
		//$error['err_file'] = $err_file;
		//$error['err_line'] = $err_line;
	}

	// 致命错误捕获
	static public function fatal_error() {
		//Log::save();

		if ($e = error_get_last()) {

			switch($e['type']) {
				case E_ERROR :
				case E_PARSE :
				case E_CORE_ERROR :
				case E_COMPILE_ERROR :
				case E_USER_ERROR :
					ob_end_clean();
					self::halt($e);
					break;
			}
		}
	}

	/**
	 * 错误输出
	 * @param mixed $error 错误
	 * @return void
	 */
	static public function halt($error) {
		$e = array();
		if (DEBUG_MODE) {

			$trace = debug_backtrace();
			$e['message'] = $error;
			$e['file'] = $trace[0]['file'];
			$e['line'] = $trace[0]['line'];
			//$trace = debug_backtrace();
			//unset($trace[0]);
			//unset($trace[1]);
			echo('<style>.layui-code-view .layui-code-ol li.red{background:#2794eb;color:#fff;}</style>');
			foreach ($trace as $line) {
				echo '<link rel="stylesheet" href="layui/css/layui.css"  media="all">';
				echo 'file:' . $line['file'] . "<br>";
				echo 'line:' . $line['line'] . "<br>";
				echo 'function:' . $line['function'] . "<br>";
				echo 'args:' . $line['args'][0] . "<br>";
				echo '<pre class="layui-code" lay-height="300px" id="' . md5($line['file']) . '">';
				echo(htmlentities(file_get_contents($line['file'])));
				echo '</pre>';
				$error_line[md5($line['file'])] = $line['line'];
			}
			$error_line = json_encode($error_line);
			echo '<script src="layui/layui.js" charset="utf-8"></script>';
			echo '<script>';
			echo "layui.use('code', function(){var $=layui.jquery;layui.code();var err_line={$error_line};for(s in err_line){console.log(err_line[s]); $('#'+ s +' li:eq('+(err_line[s]-1)+')').addClass('red'); }});";
			echo '</script>';
		}
		// 包含异常页面模板
		//$exceptionFile = C('TMPL_EXCEPTION_FILE', null, FRAMEWORK_PATH . 'Tpl/think_exception.tpl');
		//include $exceptionFile;
		exit ;
	}

	/**
	 * 添加和获取页面Trace记录
	 * @param string $value 变量
	 * @param string $label 标签
	 * @param string $level 日志级别(或者页面Trace的选项卡)
	 * @param boolean $record 是否记录日志
	 * @return void|array
	 */
	static public function trace($value = '[think]', $label = '', $level = 'DEBUG', $record = false) {
		static $_trace = array();
	}

}
?>